#ifndef __VIDEOENCODER_H__
#define __VIDEOENCODER_H__

#include "FpsCalculator.h"
#include "pch.h"
#include <boost/circular_buffer.hpp>
#include <chrono>
#include <cstdint>
#include <libavutil/buffer.h>
#include <libavutil/hwcontext.h>
#include <memory>
#include <type_traits>

class VideoEncoder
{
public:
    void Init(int fps, bool h264, const std::string &rtsp_url,const int32_t gpu_idx = 0,const int32_t core_idx = -1);

    // void SetGPU(int idx);
    void Start();
    void Stop();

    void AddImage(std::shared_ptr<ImageInfo> image);

    ~VideoEncoder();

private:
    bool _init();
    void _free();

    void EncodeThread();

private:
    int32_t _fps = 25;
    bool _h264 = true;
    std::string _rtsp_url = "";

    int32_t _width = -1;
    int32_t _height = -1;
    int32_t _gpu_index = 0;
    int32_t _core_idx = -1;

    uint32_t _frame_idx = 0;

    bool _start = false;

    std::shared_ptr<std::thread> _encode_thread;

    std::mutex _mtx;
    std::condition_variable _cv;

    std::chrono::high_resolution_clock::time_point _last_time;
    boost::circular_buffer<std::shared_ptr<ImageInfo>> _circular_queue;
    std::shared_ptr<ImageInfo> _last_image;
    NppStreamContext _npp_stream_ctx {};

    std::shared_ptr<FpsCalculator> _encode_fps = nullptr;

private:
private:
    AVFormatContext *_fmt_ctx = nullptr;
    AVCodecContext *_codec_ctx = nullptr;
    AVStream *_video_stream = nullptr;
    AVPacket *_pkt = nullptr;

    AVHWFramesContext *_frames_ctx = nullptr;

    AVBufferRef* _hw_frames_ref = nullptr;
};
#endif // __VIDEOENCODER_H__